home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************
-
- Program: < ADSP Chat >
- File: < adsp.c >
-
- Written by Pete Helm, Scott Kuechle
- of <Apple Macintosh Developer Technical Support>
-
- modified by Scott Kuechle
- 10/92 SRK Converted from Pascal to C
- 8/94 SRK Modified to use a queue of parameter
- blocks.
-
- Copyright © 1992, 1994 Apple Computer, Inc.
- All rights reserved.
-
- *****************************************************************/
-
- /*****************************************************************/
- /* I N C L U D E S
- /*****************************************************************/
-
- #include "ADSP Chat.h"
-
- /********************************************************************
- /* G L O B A L V A R I A B L E D E C L A R A T I O N S
- /********************************************************************/
-
- char myLocalSocket;
- Ptr receiveQBuffer;
- Ptr sendQBuffer;
- Ptr attnBuffer;
- Ptr outAttnBuff;
- Ptr receiveBuffer;
- Ptr outgoingDataBuffer;
-
-
- TRCCB gMyCCB; /* our ccb */
- short gADSPDrvrRefNum; /* adsp driver reference number */
- short gCCBRefNum; /* ccb reference number returned by adsp on a dspInit */
-
- Boolean gJustConnected; /* dspOpen ocRequest was successfully accepted */
-
- QHdr gAvailQueue;
- QHdr gDoneQueue;
- QHdr gReadQueue;
-
- /*****************************************************************/
- /*
- /* E X T E R N A L S
- /*
- /*****************************************************************/
-
- extern void removeMyName();
-
- extern Boolean registerMyName();
- extern void ShowError(short index);
- extern void DisplayCurrentStatus(Ptr displayStr);
- extern void HiliteConnectButton (short mode);
- extern void Exit(short message);
-
- extern Str255 gZoneString, gObjStr, gTypeStr;
- extern Str32 myName;
- extern DialogPtr myDialog;
- extern QHdr freeQHdr,saveErrorQHdr;
- extern AddrBlock ourNetworkAddress;
- extern void CopyPstr(Ptr pSource, Ptr pDest);
- extern void PStrCat(Ptr sourceStr, Ptr destinationStr);
- extern void zeroOutStrings();
- extern void PreCompletion();
-
-
-
-
- #pragma segment adsp
- // *****************************************************************
- // * doADSPinit
- // *
- // * calls dspInit, saves the socket and ccb refnum returned
- // *****************************************************************
- Boolean doADSPinit(unsigned char *localSocket,
- short *ccbRefNum,
- TPCCB ccbPtr)
- {
- TRinitParams *initParmsPtr;
- DSPParamBlock dspPB;
-
- /* allocate connection end */
- dspPB.ioCRefNum = gADSPDrvrRefNum;
- dspPB.csCode = dspInit;
-
- initParmsPtr = &dspPB.u.initParams;
-
- initParmsPtr->ccbPtr = ccbPtr;
- /* poll in main event loop instead of using user routine */
- initParmsPtr->userRoutine = NULL;
- initParmsPtr->sendQSize = Qsize;
- initParmsPtr->sendQueue = sendQBuffer;
- initParmsPtr->recvQSize = Qsize;
- initParmsPtr->recvQueue = receiveQBuffer;
- initParmsPtr->attnPtr = attnBuffer;
- initParmsPtr->localSocket = 0; /* dynamically allocate a socket for us */
-
- if (PBControl((ParmBlkPtr)&dspPB, false) != noErr)
- Exit(DrvrErr);
- else if ( dspPB.ioResult == noErr) /* any errors? */
- {
- /* save socket returned to us by ADSP */
- *localSocket = initParmsPtr->localSocket;
-
- /* save ccb reference number returned to us by ADSP */
- *ccbRefNum = dspPB.ccbRefNum;
- return true;
- }
- else /* got an error on the dspInit */
- {
- *ccbRefNum = 0;
- ShowError(dspInitErr);
- return false;
- }
- }
-
- // *****************************************************************
- // * initializeADSP
- // *
- // * opens the adsp driver, allocates memory for our adsp buffers
- // * then issues a passive open call
- // *****************************************************************
- void initializeADSP()
- {
- /* set up the ADSP connection end. */
- gJustConnected = false;
- gCCBRefNum = 0;
-
- changeConnectButtonState();
-
- /* open the ADSP driver here - we need the reference number
- for all ADSP calls */
- if (OpenDriver("\p.DSP", &gADSPDrvrRefNum) != noErr)
- Exit(atalkErr);
-
- if (InitQueues() == noErr)
- {
- /* allocate memory for our buffers and then
- issue a passive open */
- if (setUpADSPbuffers() == true)
- {
- /* issue a passive open */
- if (WaitForConnectionRequest() != true)
- {
- /* oops! got an error so deallocate our buffers */
- removeADSPBuffers();
- Exit(memErr);
- }
- }
- else
- Exit(noMemErr);
- }
- else
- Exit(memErr);
-
- }
-
-
- // *****************************************************************
- // * SetOurCompletionRoutine
- // *
- // * Sets the "real" completion routine for our async. calls
- // *****************************************************************
-
- void SetOurCompletionRoutine(ProcPtr procPtr,
- DSPPBPtr dspPBPtr)
- {
- Ptr p;
- myDSPParamBlockPtr myDSPPBPtr;
-
- p = (Ptr)dspPBPtr;
- /* the "ourCompletion" field is offset
- 8 bytes above the DSPParmBlock in
- our definition */
- myDSPPBPtr = (myDSPParamBlockPtr)(p - 8);
- myDSPPBPtr->ourCompletion = procPtr;
-
- }
-
- // *****************************************************************
- // * GetQElement
- // *
- // * retrieve a queue element from the specified queue
- // *****************************************************************
-
- DSPPBPtr GetQElement(QHdrPtr qHdrPtr)
- {
- OSErr err;
- QElemPtr qElemPtr;
-
- CheckDoneQueue();
-
- qElemPtr = qHdrPtr->qHead;
- if (qElemPtr != NULL)
- {
- err = Dequeue((QElemPtr)qElemPtr,qHdrPtr);
- if (err != noErr)
- {
- return NULL;
- }
- else
- {
- return (DSPPBPtr)(qElemPtr);
- }
- }
- else
- return NULL;
- }
-
- // *****************************************************************
- // * InitQueues
- // *
- // * initialize our "Available" , "Done" and "Read" queues
- // *****************************************************************
-
- OSErr InitQueues()
- {
- short i;
- OSErr err;
- long myA5;
- myDSPParamBlockPtr myQElem;
-
-
- gAvailQueue.qHead = NULL;
- gAvailQueue.qTail = NULL;
-
- gDoneQueue.qHead = NULL;
- gDoneQueue.qTail = NULL;
-
- gReadQueue.qHead = NULL;
- gReadQueue.qTail = NULL;
-
- err = noErr;
- myA5 = *(long *)CurrentA5;
-
- for (i=0; (i < maxQElements) || (err != noErr); ++i)
- {
- myQElem = (myDSPParamBlockPtr)NewPtr(sizeof(myDSPParamBlock));
- if (myQElem != NULL)
- {
- myQElem->myA5 = myA5;
- myQElem->u.ioCompletion = (ProcPtr)&PreCompletion;
- Enqueue((QElemPtr)&myQElem->u,&gAvailQueue);
- }
- else
- {
- err = MemError();
- }
- }
-
- return err;
- }
-
- // *****************************************************************
- // * setUpADSPbuffers
- // *
- // * allocates memory for our adsp buffers
- // *****************************************************************
- Boolean setUpADSPbuffers()
- {
-
- receiveQBuffer = NewPtr(Qsize);
- if ( receiveQBuffer == nil) return false;
-
- sendQBuffer = NewPtr(Qsize);
- if ( sendQBuffer == nil) return false;
-
- attnBuffer = NewPtr(attnBufSize);
- if ( attnBuffer == nil) return false;
-
- outAttnBuff = NewPtr(attnBufSize);
- if ( outAttnBuff == nil) return false;
-
- receiveBuffer = NewPtr(attnBufSize);
- if ( receiveBuffer == nil) return false;
-
- outgoingDataBuffer = NewPtr(Qsize);
- if ( outgoingDataBuffer == nil) return false;
-
- return true;
-
- }
-
-
-
- // *****************************************************************
- // * changeConnectButtonState
- // *
- // * sets the correct state for our connect button
- // *****************************************************************
- void changeConnectButtonState()
- {
- /* this procedure reflects the state of our connection in the control */
-
- Rect r;
- short kind;
- Handle h;
-
- GetDItem(myDialog, kConnectButtonID, &kind, &h, &r);
-
- if ( (gCCBRefNum == 0) ||
- ((gCCBRefNum != 0) && (gMyCCB.state == sClosed)) )
- SetCTitle((ControlHandle)h, "\pConnect");
- else
- {
- SetCTitle((ControlHandle)h, "\pDisconnect");
- HiliteConnectButton(0);
- }
- }
-
- // *****************************************************************
- // * DisplayTime
- // *
- // * this procedure responds to an attention message from the remote
- // * Mac which contains the time of that Mac. Silly yes, but it does
- // * show how to use the attnMsg stuff.
- // *****************************************************************
- void DisplayTime()
- {
-
- Rect r;
- short kind;
- Handle h;
- long dateTime;
- Str255 str, str2;
-
- GetDItem(myDialog, kRemoteMacsTimeID, &kind, &h, &r);
- GetIText(h, str2);
- BlockMove(attnBuffer, &dateTime, 4);
- IUTimeString(dateTime, true, str);
-
- /* this just checks to see that we're not already displaying this time already */
- /* flashing text sucks... so sayeth me */
- if (IUCompString(str,str2) != 0)
- SetIText(h, str);
- }
-
- // *****************************************************************
- // * DisplayTheirName
- // *
- // * this procedure responds to an attention message from the remote
- // * Mac which contains the remote Mac's Chooser name.
- // *****************************************************************
- void DisplayTheirName()
- {
-
- Rect r;
- short kind;
- Handle h;
- Str255 str;
-
- GetDItem(myDialog, kRemoteMacsNameID, &kind, &h, &r);
- BlockMove(attnBuffer, &str, 255);
- SetIText(h, str);
- }
-
- // *****************************************************************
- // * DisplayIncomingText
- // *
- // * this procedure takes the text written to our receive buffer from
- // * the remote Mac and displays the text in a dialog item
- // *****************************************************************
- void DisplayIncomingText(DSPPBPtr dspPBPtr)
- {
-
- Rect r;
- short kind;
- Handle h;
- Str255 str;
-
- GetDItem(myDialog, kIncomingTextID, &kind, &h, &r);
- BlockMove(dspPBPtr->u.ioParams.dataPtr, (Ptr)(&str[1]), 255);
-
- str[0] = (char)dspPBPtr->u.ioParams.actCount;
- SetIText(h, &str);
-
- }
-
-
- // *****************************************************************
- // * removeADSPBuffers
- // *
- // * this procedure deallocates the memory for our adsp buffers.
- // *****************************************************************
- void removeADSPBuffers()
- {
- if (receiveQBuffer != NULL)
- DisposPtr(receiveQBuffer);
- if (sendQBuffer != NULL)
- DisposPtr(sendQBuffer);
- if (attnBuffer != NULL)
- DisposPtr(attnBuffer);
- if (outAttnBuff != NULL)
- DisposPtr(outAttnBuff);
- if (receiveBuffer != NULL)
- DisposPtr(receiveBuffer);
- if (outgoingDataBuffer != NULL)
- DisposPtr(outgoingDataBuffer);
-
- }
-
- // *****************************************************************
- // * CloseTheConnection
- // *
- // * calls dspClose to close the connection end.
- // *****************************************************************
- void CloseTheConnection(short ccbRefNum)
- {
- DSPParamBlock pb;
-
- pb.ioCRefNum = gADSPDrvrRefNum;
- pb.csCode = dspClose;
- pb.ccbRefNum = ccbRefNum;
- pb.u.closeParams.abort = 1; /* non zero value aborts any outstanding calls */
-
- if (PBControl((ParmBlkPtr)&pb, false) != noErr)
- Exit(DrvrErr);
- }
-
-
- // *****************************************************************
- // * removeConnectionEnd
- // *
- // * calls dspRemove to eliminate the connection end.
- // *****************************************************************
- void removeConnectionEnd(short ccbRefNum)
- {
- DSPParamBlock pb;
-
- pb.ioCRefNum = gADSPDrvrRefNum;
- pb.csCode = dspRemove;
- pb.ccbRefNum = ccbRefNum;
- pb.u.closeParams.abort = 1; /* non zero value aborts any outstanding calls */
-
- if (PBControl((ParmBlkPtr)&pb, false) != noErr)
- Exit(DrvrErr);
-
- if (pb.ioResult != noErr)
- ShowError(dspRemoveErr);
- }
-
- // *****************************************************************
- // * WaitForConnectionRequest
- // *
- // * calls dspInit to establish a connection end. Then registers
- // * our name on the net and does a passive open.
- // *****************************************************************
- Boolean WaitForConnectionRequest()
- {
- DSPPBPtr dspPBPtr;
-
- /* first issue a dspInit */
- if (doADSPinit(&myLocalSocket,
- &gCCBRefNum,
- &gMyCCB) == true)
- {
- /* save our socket for comparison purposes later */
- ourNetworkAddress.aSocket = myLocalSocket;
-
- /* now register our nbp name with type "moof" */
- if (registerMyName() == true)
- {
- /* get QElement for the dspInit call */
- dspPBPtr = GetQElement(&gAvailQueue);
- if (dspPBPtr != NULL)
- {
- /* do a passive open, waiting for open requests */
- DoPassiveOpen(dspPBPtr,
- gCCBRefNum);
- return true;
- }
- }
- else /* we got an error! */
- { /* remove connection end with dspRemove */
- removeConnectionEnd(gCCBRefNum);
- /* de-allocate memory we got for our buffers */
- removeADSPBuffers();
- }
- }
-
- return false;
- }
-
- // *****************************************************************
- // * CloseConnection
- // *
- // * calls dspRemove to eliminate the connection end. Then removes
- // * our nbp name from the net and re-issues a passive open.
- // *****************************************************************
- void CloseConnection()
- {
- /* do a dspRemove to close the connection end */
- removeConnectionEnd(gCCBRefNum);
-
- /* remove our nbp name "moof" */
- removeMyName();
-
- changeConnectButtonState();
- zeroOutStrings();
-
- /* at this point, we have closed the connection so let's issue
- an asynchronous passive open. This call will complete whenever
- we receive an open connection request from another machine. */
- WaitForConnectionRequest();
-
- }
-
-
- // *****************************************************************
- // * sendAttnMsgCompRoutine
- // *
- // * when our send attention message call completes this procedure
- // * will get called.
- // *****************************************************************
- pascal void sendAttnMsgCompRoutine(DSPPBPtr dspPBPtr)
- {
- if (dspPBPtr->ioResult == noErr)
- /* place parameter block back into the "Available" queue */
- Enqueue((QElemPtr)dspPBPtr,&gAvailQueue);
- else /* some kind of error was returned */
- /* place parameter block back into the "Done" queue */
- Enqueue((QElemPtr)dspPBPtr,&gDoneQueue);
- }
-
- // *****************************************************************
- // * sendAttnMsg
- // *
- // * this is a generic attention message sending routine. all
- // * attention messages are sent async using a shared buffer.
- // * the message code and the size of the message are passed to
- // * this proc.
- // *****************************************************************
- void sendAttnMsg(DSPPBPtr dspPBPtr,
- short buffSize,
- Ptr attnData,
- short msg,
- short ccbRefNum)
- {
- TRattnParams *attnParmsPtr;
-
- /* this is a generic attention message sending routine. all attention messages are sent*/
- /* async using a shared buffer. the message code and the size of the message are passed to */
- /* this proc.*/
-
- SetOurCompletionRoutine((ProcPtr)&sendAttnMsgCompRoutine,
- dspPBPtr);
-
- dspPBPtr->ioCRefNum = gADSPDrvrRefNum;
- dspPBPtr->csCode = dspAttention;
- dspPBPtr->ccbRefNum = ccbRefNum;
-
- attnParmsPtr = &dspPBPtr->u.attnParams;
- attnParmsPtr->attnCode = (unsigned short)msg;
- attnParmsPtr->attnSize = buffSize;
- attnParmsPtr->attnData = attnData;
- attnParmsPtr->attnInterval = 10;
-
- if (PBControl((ParmBlkPtr)dspPBPtr, true) != noErr)
- Exit(DrvrErr);
- }
-
-
- // *****************************************************************
- // * OpenPassiveCompletionRtn
- // *
- // * when our passive open call completes this procedure
- // * will get called.
- // *****************************************************************
- pascal void OpenPassiveCompletionRtn(DSPPBPtr dspPBPtr)
- {
-
- if (dspPBPtr->ioResult == noErr)
- {
- gJustConnected = true;
- /* issue a read so we can catch
- any messages sent to us */
- readIncoming(dspPBPtr,
- gCCBRefNum);
- }
- else
- /* place parameter block back into the "Done" queue */
- Enqueue((QElemPtr)dspPBPtr,&gDoneQueue);
- }
-
-
- // *****************************************************************
- // * DoPassiveOpen
- // *
- // * issues an asynchronous passive open call. Any machine wishing
- // * to connect to us must only send us an open request (dspOpen,
- // * ocRequest mode). Once we get a request, our completion routine
- // * is called and the connection is established.
- // *****************************************************************
- void DoPassiveOpen(DSPPBPtr dspPBPtr,
- short ccbRefNum)
- {
- AddrBlock filterAddress;
- TRopenParams *openPBPtr;
-
-
- /* send an open request */
- SetOurCompletionRoutine((ProcPtr)&OpenPassiveCompletionRtn,
- dspPBPtr);
- dspPBPtr->ioCRefNum = gADSPDrvrRefNum;
- dspPBPtr->csCode = dspOpen;
- dspPBPtr->ccbRefNum = ccbRefNum; /* refNum of connection end */
-
- /* accept open requests from anyone */
- filterAddress.aNet = 0;
- filterAddress.aNode = 0;
- filterAddress.aSocket = 0;
-
- openPBPtr = &dspPBPtr->u.openParams;
- openPBPtr->filterAddress = filterAddress;
- openPBPtr->ocMode = ocPassive;
- openPBPtr->ocInterval = 0; /* use default value of 6 (1 second) */
- openPBPtr->ocMaximum = 255; /* retransmit indefinitely */
-
- if (PBControl((ParmBlkPtr)dspPBPtr, true) != noErr)
- Exit(dspOpenErr);
-
- }
-
- // *****************************************************************
- // * adspOpenRqstCompletionRtn
- // *
- // * when our open request call completes this procedure
- // * will get called. If we dont get back any errors then the
- // * connection is established with the target.
- // *****************************************************************
- pascal void adspOpenRqstCompletionRtn(DSPPBPtr dspPBPtr)
- {
- if (dspPBPtr->ioResult == noErr)
- {
- gJustConnected = true;
- /* issue a read so we can catch
- any messages sent to us */
- readIncoming(dspPBPtr,
- gCCBRefNum);
- }
- else
- /* place parameter block back into the "Done" queue */
- Enqueue((QElemPtr)dspPBPtr,&gDoneQueue);
- }
-
- // *****************************************************************
- // * sendAnOpenConnReq
- // *
- // * issues an open request call to the target.
- // *****************************************************************
- void sendAnOpenConnReq (DSPPBPtr dspPBPtr,
- AddrBlock theirAddress,
- short ccbRefNum)
- {
- AddrBlock filterAddress;
- TRopenParams *openPBPtr;
-
- /* make a connection only with the selected target */
- filterAddress = theirAddress;
-
- /* send an open request */
- SetOurCompletionRoutine((ProcPtr)&adspOpenRqstCompletionRtn,
- dspPBPtr);
- dspPBPtr->ioCRefNum = gADSPDrvrRefNum;
- dspPBPtr->csCode = dspOpen;
- dspPBPtr->ccbRefNum = ccbRefNum;
-
- /* refNum of connection end */
- openPBPtr = &dspPBPtr->u.openParams;
- openPBPtr->remoteAddress = theirAddress;
- openPBPtr->filterAddress = filterAddress;
- openPBPtr->ocMode = ocRequest;
- openPBPtr->ocInterval = 6;
- openPBPtr->ocMaximum = 5;
-
- if (PBControl((ParmBlkPtr)dspPBPtr, true) != noErr)
- Exit(dspOpenErr);
-
- }
-
- // *****************************************************************
- // * connectToPeer
- // *
- // * first checks to see if the target is still there. Next, it
- // * issues an open request to the target (but it first closes
- // * the connection end which forces any prior passive open calls to
- // * complete).
- // *****************************************************************
- void connectToPeer()
- {
- NBPparms *nbpParms;
- MPPParamBlock pbLKP;
- char returnBuffer[kLookupBufSize];
- EntityName abEntity;
- AddrBlock address;
- NamesTableEntry namesTableEntry;
- DSPPBPtr dspPBPtr;
-
- if (gMyCCB.state == sClosed ||
- gMyCCB.state == sPassive)
- {
- NBPSetEntity((Ptr)&namesTableEntry, gObjStr, gTypeStr, gZoneString);
-
- nbpParms = &pbLKP.NBP;
-
- nbpParms->interval = 3;
- nbpParms->count = 3;
- nbpParms->NBPPtrs.entityPtr = (Ptr)&namesTableEntry;
- nbpParms->parm.Lookup.retBuffSize = kLookupBufSize;
- nbpParms->parm.Lookup.retBuffPtr = &returnBuffer;
- nbpParms->parm.Lookup.maxToGet = 1;
-
- /* see if the target still exists */
- if (PLookupName(&pbLKP, false) == noErr)
- {
- if ( nbpParms->parm.Lookup.numGotten > 0)
- {
- /* look for the target in our return buffer */
- if (NBPExtract(returnBuffer,
- nbpParms->parm.Lookup.numGotten,
- 1,
- &abEntity,
- &address) == noErr)
- {
- /* if a passive open has been issued, we must first close the connection end (which
- will cancel the open) before we can issue an open request to the target */
- if (gMyCCB.state == sPassive)
- {
- CloseTheConnection(gCCBRefNum);
- }
-
- dspPBPtr = GetQElement(&gAvailQueue);
- if (dspPBPtr != NULL)
- {
- /* issue an open request to the target */
- sendAnOpenConnReq(dspPBPtr,
- address,
- gCCBRefNum);
- }
- }
-
- }
- else /* target not found */
- ShowError(noTargetErr);
- }
-
- }
- else /* disconnect */
- {
- CloseConnection();
- }
- }
-
- // *****************************************************************
- // * readIncomingComp
- // *
- // * this routine is called when our asynchronous dspRead call
- // * completes.
- // *****************************************************************
- pascal void readIncomingComp(DSPPBPtr dspPBPtr)
- {
- if (dspPBPtr->ioResult == noErr)
- {
- /* place parameter block back into the "Read" queue */
- Enqueue((QElemPtr)dspPBPtr,&gReadQueue);
- }
- else /* error occurred */
- {
- /* place parameter block back into the "Done" queue */
- Enqueue((QElemPtr)dspPBPtr,&gDoneQueue);
- }
-
- }
-
- // *****************************************************************
- // * readIncoming
- // *
- // * issues an asynchronous dspRead to read any incoming messages
- // *****************************************************************
- void readIncoming(DSPPBPtr dspPBPtr,
- short ccbRefNum)
- {
- TRioParams *ioPBPtr;
-
- SetOurCompletionRoutine((ProcPtr)&readIncomingComp,
- dspPBPtr);
- dspPBPtr->ioCRefNum = gADSPDrvrRefNum;
- dspPBPtr->csCode = dspRead;
- dspPBPtr->ccbRefNum = ccbRefNum;
-
- ioPBPtr = &dspPBPtr->u.ioParams;
- ioPBPtr->reqCount = Qsize;
- ioPBPtr->dataPtr = receiveBuffer;
-
- if (PBControl((ParmBlkPtr)dspPBPtr, true) != noErr)
- Exit(DrvrErr);
-
- }
-
- // *****************************************************************
- // * writeComp
- // *
- // * when our asynchronous dspWrite completes this routine will get
- // * called.
- // *****************************************************************
- pascal void writeComp(DSPPBPtr dspPBPtr)
- {
- /* place parameter block back into the "Done" queue */
- Enqueue((QElemPtr)dspPBPtr,&gDoneQueue);
- }
-
- // *****************************************************************
- // * writeOutgoing
- // *
- // * issues an asynchronous dspWrite which sends any text that has
- // * been entered to the target machine.
- // *****************************************************************
- void writeOutgoing(DSPPBPtr dspPBPtr,
- short ccbRefNum,
- Ptr dataPtr,
- short reqCount)
- {
- TRioParams *ioPBPtr;
-
- SetOurCompletionRoutine((ProcPtr)&writeComp,
- dspPBPtr);
- dspPBPtr->ioCRefNum = gADSPDrvrRefNum;
- dspPBPtr->csCode = dspWrite;
- dspPBPtr->ccbRefNum = ccbRefNum;
-
- ioPBPtr = &dspPBPtr->u.ioParams;
- ioPBPtr->reqCount = reqCount;
- ioPBPtr->dataPtr = dataPtr;
- ioPBPtr->eom = 1;
- ioPBPtr->flush = 1;
-
- if (PBControl((ParmBlkPtr)dspPBPtr, true) != noErr)
- Exit(DrvrErr);
-
- }
-
- // *****************************************************************
- // * sendTime
- // *
- // * this procedure sends an attention message packet with our
- // * time to the remote Mac.
- // *****************************************************************
- void sendTime()
- {
- unsigned long secs;
- DSPPBPtr dspPBPtr;
-
- GetDateTime(&secs);
- BlockMove(&secs, outAttnBuff, 4);
- dspPBPtr = GetQElement(&gAvailQueue);
- if (dspPBPtr != NULL)
- {
- sendAttnMsg(dspPBPtr,
- 4,
- outAttnBuff,
- kDisplayTime,
- gCCBRefNum);
- }
- }
-
- // *****************************************************************
- // * sendMyName
- // *
- // * this procedure sends an attention message packet with our
- // * Chooser name to the remote Mac.
- // *****************************************************************
- void sendMyName()
- {
- DSPPBPtr dspPBPtr;
- Str255 str;
-
- BlockMove(myName,str,myName[0]+1);
- BlockMove(&str, outAttnBuff, 256);
-
- dspPBPtr = GetQElement(&gAvailQueue);
- if (dspPBPtr != NULL)
- {
- sendAttnMsg(dspPBPtr,
- 256,
- outAttnBuff,
- kDisplayTheirName,
- gCCBRefNum);
- }
- }
-
-
- // *****************************************************************
- // * signalConnect
- // *
- // * after our passive open call has completed with an open request,
- // * or after an open request that we have issued to the target has
- // * completed, we set a flag which causes this routine to get called.
- // * This routine then sends the Chooser name of our machine to the
- // * target.
- // *****************************************************************
- void signalConnect()
- {
-
- SysBeep(1);
- changeConnectButtonState();
-
- /* send our machine's name to the other end */
- sendMyName();
-
- /*Change selection to outgoing text TERecord */
- SelIText(myDialog, kOutgoingTextID, 0, 32767);
- }
-
- // *****************************************************************
- // * checkAttnMsgs
- // *
- // * If an attention message has been sent, we process it here.
- // *****************************************************************
- void checkAttnMsgs()
- {
- switch(gMyCCB.attnCode)
- {
- case kDisplayTime:
- DisplayTime();
- break;
- case kDisplayTheirName:
- DisplayTheirName();
- break;
- }
- }
-
- // *****************************************************************
- // * DoConnectionEvents
- // *
- // * This routine checks for unsolicited connection events and
- // * processes them accordingly.
- // *****************************************************************
- void DoConnectionEvents()
- {
- short state;
- Byte flags;
-
- state = gMyCCB.state;
- flags = gMyCCB.userFlags;
-
- if (state == sOpen)
- DisplayCurrentStatus("\pConnection established.");
- else if (state == sClosed)
- DisplayCurrentStatus("\pNot currently connected.");
- else if (state == sPassive)
- DisplayCurrentStatus("\pWaiting to accept connection.");
-
- if (flags & eAttention)
- {
- checkAttnMsgs();
- /* we must clear the bit after we have used it or we wont
- get any more messages */
- BitClr(&gMyCCB.userFlags,2);
- }
- else if (flags & eClosed)
- {
- DisplayCurrentStatus("\pConnection was closed.");
- /* we must clear the bit after we have used it or we wont
- get any more messages */
- BitClr(&gMyCCB.userFlags,0);
- CloseConnection();
- }
- /* after two minutes or so if the connection has broken we'll be notified by */
- /* the .DSP driver with an eTearDown message */
- else if (flags & eTearDown)
- {
- SysBeep(2);
- SysBeep(2);
- DisplayCurrentStatus("\pConnection torn down.");
- /* we must clear the bit after we have used it or we wont
- get any more messages */
- BitClr(&gMyCCB.userFlags,1);
- CloseConnection();
- }
-
- }
-
- // *****************************************************************
- // * CheckDoneQueue
- // *
- // * This routine looks through the "Done" queue for calls that
- // * have completed and reports any errors.
- // *****************************************************************
- void CheckDoneQueue()
- {
- QElemPtr qElemPtr;
- DSPPBPtr dspPBPtr;
- OSErr err;
-
- /* have any Writes completed? */
- if (gDoneQueue.qHead != nil)
- {
- qElemPtr = gDoneQueue.qHead;
- err = Dequeue((QElemPtr)qElemPtr,&gDoneQueue);
- if (err == noErr)
- {
- dspPBPtr = (DSPPBPtr)qElemPtr;
- /* were there any errors on this particular call? */
- if (dspPBPtr->ioResult != noErr)
- {
- ShowADSPError(dspPBPtr);
- }
-
- /* place queue element back into the "available" queue */
- Enqueue((QElemPtr)qElemPtr,&gAvailQueue);
- }
- }
-
- }
-
- // *****************************************************************
- // * CheckCompletedReads
- // *
- // * This routine looks through the "Read" queue for calls that
- // * have completed, displays the text that was read and re-issues
- // * another asynchronous read call.
- // *****************************************************************
- void CheckCompletedReads()
- {
- QElemPtr qElemPtr;
- DSPPBPtr dspPBPtr;
- OSErr err;
-
- /* have any reads completed? */
- if (gReadQueue.qHead != nil)
- {
- qElemPtr = gReadQueue.qHead;
- err = Dequeue((QElemPtr)qElemPtr,&gReadQueue);
- if (err == noErr)
- {
- dspPBPtr = (DSPPBPtr)qElemPtr;
- /* were there any errors on this particular read call? */
- if (dspPBPtr->ioResult == noErr)
- {
- /* show the text */
- DisplayIncomingText(dspPBPtr);
- }
- else
- {
- ShowADSPError(dspPBPtr);
- }
-
- /* go ahead and issue another asynchronous read */
- readIncoming(dspPBPtr,
- gCCBRefNum);
- }
- }
-
- }
-
- // *****************************************************************
- // * ADSPLoop
- // *
- // * This is called from our idle procedure in our main event
- // * loop. If a connection is made, we learn about it here. If we
- // * do detect that a connection has been made, we check for
- // * connection events and issue read and write calls here.
- // *****************************************************************
- void ADSPLoop()
- {
-
- /* check to see if our passive open completed with an open
- request from another machine OR if an open request that
- we issued to the target has completed */
- if (gJustConnected == true)
- {
- /* reset our flag */
- gJustConnected = false;
-
- /* set status message to indicate we have a connection */
- signalConnect();
- }
-
- /* check for connection events */
- DoConnectionEvents();
-
- if (gMyCCB.state != sClosed)
- {
- /* have any read calls completed? */
- CheckCompletedReads();
-
- /* check for all other calls that have completed */
- CheckDoneQueue();
- }
-
- /* do we currently have a connection? */
- if (gMyCCB.state == sOpen)
- {
- /* we have a connection so send our clock time
- to the other machine */
- sendTime();
-
- }
-
-
- }
-
-
- // *****************************************************************
- // * SetUpADSPError
- // *
- // * sets our error string for the desired error code
- // *****************************************************************
- void SetUpADSPError(OSErr err, StringPtr displayStr)
- {
- switch (err)
- {
- case errAborted:
- PStrCat("\pControl call was aborted.",(Ptr)displayStr);
- break;
-
- case errState:
- PStrCat("\pBad connection state for this operation.",(Ptr)displayStr);
- break;
-
- case errOpening:
- PStrCat("\pOpen connection request failed.",(Ptr)displayStr);
- break;
-
- case errOpenDenied:
- PStrCat("\pOpen connection request was denied.",(Ptr)displayStr);
- break;
-
- default:
- NumToString(err,(Ptr)displayStr);
-
- }
-
- }
-
- // *****************************************************************
- // * ShowADSPError
- // *
- // * If one of our asynchronous adsp calls returned an error, the
- // * parameter block gets stuffed into an error OSQueue by the completion
- // * routine. This error queue is checked periodically by this routine.
- // * If the queue is not empty, then we got an error so we display it here
- // * and do any processing of the error that we want.
- // *****************************************************************
- void ShowADSPError(DSPPBPtr dspPBPtr)
- {
- short itemHit;
- Str255 displayStr,theError;
-
-
- displayStr[0] = 0;
-
- /* Use cscode field of the parameter block
- to see which call this error is for*/
-
- switch (dspPBPtr->csCode)
- {
- case dspRead:
- /* We'll ignore the "errState" error for now,
- since you'll get this when you close a
- connection (and we don't really need to
- report it in that case) */
- if (dspPBPtr->ioResult != errState)
- {
- CopyPstr("\pdspRead error. ",&displayStr);
- SetUpADSPError(dspPBPtr->ioResult, &displayStr);
- }
- break;
-
- case dspWrite:
- CopyPstr("\pdspWrite error. ",&displayStr);
- SetUpADSPError(dspPBPtr->ioResult, &displayStr);
- break;
-
- case dspAttention:
- /* ignore aborts that were caused by dspRemove or dspClose */
- if ((dspPBPtr->ioResult != errAborted)
- && (dspPBPtr->ioResult != errState))
- {
- CopyPstr("\pdspAttention error. ",&displayStr);
- SetUpADSPError(dspPBPtr->ioResult, &displayStr);
- }
- break;
-
- case dspOpen:
- /* ignore errAborted (-1279), request aborted by dspRemove or
- dspClose - the reason being that if we have a dspOpen (ocPassive
- mode) issued and then we want to connect to another machine, we
- must first close the connection end (cancelling the passive open)
- which would result in this error */
- if (dspPBPtr->ioResult != errAborted)
- {
- CopyPstr("\pdspOpen error. ",&displayStr);
- SetUpADSPError(dspPBPtr->ioResult, &displayStr);
- }
- break;
-
- case dspCLListen:
- CopyPstr("\pdspCLListen error. ",&displayStr);
- SetUpADSPError(dspPBPtr->ioResult, &displayStr);
- break;
-
- default:
- CopyPstr("\pError: ",&displayStr);
- NumToString(dspPBPtr->ioResult,theError);
- PStrCat(theError,(Ptr)displayStr);
- }
-
- /* if we have a message we want to show, put up a dialog
- for the user */
- if (displayStr[0] != 0)
- {
- ParamText(displayStr,"\p","\p","\p");
- itemHit = Alert(rErrorDialog, nil);
- }
- }